package tx.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tx.dao.BookDao;

@Service
public class BookServiceImpl implements BookService {
    @Autowired
    private BookDao bookDao;

    //隔离级别
//    读未提交：READ UNCOMMITTED
//    允许Transaction01读取Transaction02未提交的修改。
//    读已提交：READ COMMITTED、
//    要求Transaction01只能读取Transaction02已提交的修改。
//    可重复读：REPEATABLE READ
//    确保Transaction01可以多次从一个字段中读取到相同的值，即Transaction01执行期间禁止其它事务对这个字段进行更新。
//    串行化：SERIALIZABLE
//    确保Transaction01可以多次从一个表中读取到相同的行，在Transaction01执行期间，禁止其它事务对这个表进行添加、更新、删除操作。可以避免任何并发问题，但性能十分低下。

    //传播行为
//    REQUIRED：支持当前事务，如果不存在就新建一个(默认)**【没有就新建，有就加入】**
//    SUPPORTS：支持当前事务，如果当前没有事务，就以非事务方式执行**【有就加入，没有就不管了】**
//    MANDATORY：必须运行在一个事务中，如果当前没有事务正在发生，将抛出一个异常**【有就加入，没有就抛异常】**
//    REQUIRES_NEW：开启一个新的事务，如果一个事务已经存在，则将这个存在的事务挂起**【不管有没有，直接开启一个新事务，开启的新事务和之前的事务不存在嵌套关系，之前事务被挂起】**
//    NOT_SUPPORTED：以非事务方式运行，如果有事务存在，挂起当前事务**【不支持事务，存在就挂起】**
//    NEVER：以非事务方式运行，如果有事务存在，抛出异常**【不支持事务，存在就抛异常】**
//    NESTED：如果当前正有一个事务在进行中，则该方法应当运行在一个嵌套式事务中。被嵌套的事务可以独立于外层事务进行提交或回滚。如果外层事务不存在，行为就像REQUIRED一样。**【有事务的话，就在这个事务里再嵌套一个完全独立的事务，嵌套的事务可以独立的提交和回滚。没有事务就和REQUIRED一样。】**

    @Transactional() //表示事务
    //利用事务回滚与用户余额不为负值
        //用户余额为负值 时 事务回滚 （原子性）
    @Override
    public void buyBook(Integer bookId, Integer userId) {
        //根据图示Id查询图书价格
        Integer price = bookDao.getBookPriceByBookId(bookId);
        //更新图书表库存量 -1
        bookDao.updateStock(bookId);
        //更新用户表用户余额
        bookDao.updateUserBalance(userId,price);

    }
}
